package cpoo.util;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;

import cpoo.exceptions.MotionException;
import cpoo.globalMotion.MotionVector;
import cpoo.painting.FrameInfo;

public class Loger {
	File output;
	public Loger(File f){
		output = f;
	}
	
	public void clearLog(){
		FileWriter writer = null;
		try {
			writer = new FileWriter(output, false);
			writer.write("");
		} catch (IOException e) {
			System.err.println("clearing log FAILED");
		} finally {
			if (writer != null){
				try {
					writer.close();
				} catch (IOException e) {
					System.err.println("Closing log file FAILED");
				}
			}
		}
	}
	
	public void log(double[] transformation){
		FileWriter writer = null;
		try {
			writer = new FileWriter(output, true);
			for (int i=0; i<transformation.length; i++){
				writer.write(transformation[i]+";");
			}
			writer.write("\n");
		} catch (IOException e) {
			System.err.println("Logging of object '"+transformation+"' FAILED");
		} finally {
			if (writer != null){
				try {
					writer.close();
				} catch (IOException e) {
					System.err.println("Closing log file FAILED");
				}
			}
		}
	}
	
	public AffineTransform[] readAffineTransformations() throws MotionException{
		FileReader fileReader = null;
		BufferedReader reader = null;
		
		ArrayList<AffineTransform> result = new ArrayList<AffineTransform>();
		try {
			fileReader = new FileReader(output);
			reader = new BufferedReader(fileReader);
			String line = null;
			
			while ((line = reader.readLine()) != null && line != ""){
				StringTokenizer tokenizer = new StringTokenizer(line, ";");
				double[] transformMatrix = new double[6];
				for (int i=0; i<6 && tokenizer.hasMoreElements(); i++){
					String value = tokenizer.nextToken();
					//double v = 0.0;
					try {
						transformMatrix[i] = Double.parseDouble(value);
					}catch (NumberFormatException nfe) {
						
					}
				}
				result.add(new AffineTransform(transformMatrix));
			}
		} catch (IOException e) {
			System.err.println("Reading transformations FAILED");
			throw new MotionException(e, "Reading transformations FAILED");
		}
		return result.toArray(new AffineTransform[0]);
	}
	
	public FrameInfo[] readObjects(AffineTransform[] globalMotion, Dimension frameSize) throws MotionException{
		FileReader fileReader = null;
		BufferedReader reader = null;
		
		ArrayList<FrameInfo> result = new ArrayList<FrameInfo>();
		try {
			fileReader = new FileReader(output);
			reader = new BufferedReader(fileReader);
			String line = null;
			
			int frameNumber = 1;
			Point point = new Point(0,0);
			
			while ((line = reader.readLine()) != null && line != ""){
				FrameInfo frameInfo = new FrameInfo(frameNumber, new Rectangle(point.x, point.y, frameSize.width, frameSize.height));
				AffineTransform tr = globalMotion[frameNumber-1];
				if (tr == null){
					throw new MotionException(null, "Not enough transformations found");
				}
				tr.transform(point, point);
				StringTokenizer tokenizer = new StringTokenizer(line, ";");
				//double[] transformMatrix = new double[6];
				while (tokenizer.hasMoreElements()){
					String value = tokenizer.nextToken();
					Rectangle object = null;
					if ("null".compareTo(value) == 0){
						frameInfo.addObject(null);
					} else {
						StringTokenizer innerTokenizer = new StringTokenizer(value, ",");
						String ulXs = innerTokenizer.nextToken();
						String ulYs = innerTokenizer.nextToken();
						String widthS = innerTokenizer.nextToken();
						String heightS = innerTokenizer.nextToken();
						
						try {
							int ulX = Integer.parseInt(ulXs);
							int ulY = Integer.parseInt(ulYs);
							int width = Integer.parseInt(widthS);
							int height = Integer.parseInt(heightS);
							
							object = new Rectangle(ulX, ulY, width, height);
						}catch (NumberFormatException nfe) {
							
						}
					}
					//double v = 0.0;
					if (tokenizer.hasMoreTokens()){
						frameInfo.addObject(object);
					} else {
						frameInfo.setDisappearingObject(object);
					}
				}
				result.add(frameInfo);
				frameNumber ++;
			}
		} catch (IOException e) {
			System.err.println("Reading transformations FAILED");
			throw new MotionException(e, "Reading transformations FAILED");
		}
		return result.toArray(new FrameInfo[0]);
	}
	
	public MotionVector[][] readVectors () throws MotionException{
		FileReader fileReader = null;
		BufferedReader reader = null;
		
		ArrayList<MotionVector[]> result = new ArrayList<MotionVector[]>();
		try {
			fileReader = new FileReader(output);
			reader = new BufferedReader(fileReader);
			String line = null;
			
			while ((line = reader.readLine()) != null && line != ""){
				StringTokenizer tokenizer = new StringTokenizer(line, ";");
				ArrayList<MotionVector> vectors = new ArrayList<MotionVector>();
				
				while (tokenizer.hasMoreElements()){
					String value = tokenizer.nextToken();
					StringTokenizer innerTokenizer = new StringTokenizer(value, " ");
					String bxs = innerTokenizer.nextToken();
					String bys = innerTokenizer.nextToken();
					String exs = innerTokenizer.nextToken();
					String eys = innerTokenizer.nextToken();
					//double v = 0.0;
					
					try {
						int bx = Integer.parseInt(bxs);
						int by = Integer.parseInt(bys);
						int ex = Integer.parseInt(exs);
						int ey = Integer.parseInt(eys);
						
						vectors.add(new MotionVector(new Point(bx,by), new Point(ex,ey)));
					}catch (NumberFormatException nfe) {
						
					}
				}
				result.add(vectors.toArray(new MotionVector[0]));
			}
		} catch (IOException e) {
			System.err.println("Reading transformations FAILED");
			throw new MotionException(e, "Reading transformations FAILED");
		}
		return result.toArray(new MotionVector[0][0]);
	}
	
	public void saveVectors (Point[] begginings, Point[] ends){
		FileWriter writer = null;
		try {
			writer = new FileWriter(output, true);
			for (int i = 0; i< begginings.length; i++){
				Point beg = begginings[i];
				Point end = ends[i];
				
				writer.write(beg.x+" ");
				writer.write(beg.y+" ");
				writer.write(end.x+" ");
				writer.write(end.y+";");
			}
			writer.write("\n");
		} catch (IOException e) {
			System.err.println("Logging of object '"+begginings+ends+"' FAILED");
		} finally {
			if (writer != null){
				try {
					writer.close();
				} catch (IOException e) {
					System.err.println("Closing log file FAILED");
				}
			}
		}
		
	}
}
